package com.example.demo.config;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.TemplateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Column;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

import java.sql.Types;
import java.util.*;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class MybatisPlusGenerator {
    private static final String DB_URL = "jdbc:mysql://localhost:3306/demo?useSSL=false";
    private static final String DB_USERNAME = "root";
    private static final String DB_PASSWORD = "123456";
    private static final List<String> TABLES = Arrays.asList(
            "user_info",
            "system_log"
    );
    private static final String AUTHOR = "chenzl";
    private static final String PKG_PARENT = "com.example.demo";
    private static final String PKG_ENTITY = "model";
    private static final String PKG_MAPPER = "dao";

    /**
     * 数据源配置
     */
    private static final DataSourceConfig DATA_SOURCE_CONFIG = new DataSourceConfig.Builder(DB_URL, DB_USERNAME, DB_PASSWORD)
            //数据库 schema(部分数据库适用)	mybatis-plus
            //.schema("demo")
            .typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
                int typeCode = metaInfo.getJdbcType().TYPE_CODE;
                if (typeCode == Types.SMALLINT) {
                    // 自定义类型转换
                    return DbColumnType.INTEGER;
                }
                return typeRegistry.getColumnType(metaInfo);
            })
            .build();

    private static final GlobalConfig GLOBAL_CONFIG = new GlobalConfig.Builder()
            //禁止打开输出目录	默认值:true
            .disableOpenDir()
            //指定输出目录
            .outputDir(System.getProperty("user.dir") + "/src/main/java")
            //设置作者
            .author(AUTHOR)
            //开启swagger模式
            .enableSwagger()
            //时间策略	DateType.ONLY_DATE 默认值: DateType.TIME_PACK
            //.dateType(DateType.TIME_PACK)
            //注释日期	默认值: yyyy-MM-dd
            //.commentDate("yyyy-MM-dd HH:mm:ss")
            .build();

    private static final PackageConfig PACKAGE_CONFIG = new PackageConfig.Builder()
            //设置父包名
            .parent(PKG_PARENT)
            //父包模块名	默认值:无
            //.moduleName("demo")
            .entity(PKG_ENTITY)
            //Mapper包名 默认值:mapper
            .mapper(PKG_MAPPER)
            //设置mapperXml生成路径
            .pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "/src/main/resources/mapper"))
            .build();

    private StrategyConfig strategyConfig;

    private void initStrategyConfig() {
        strategyConfig = new StrategyConfig.Builder()
                // 设置需要生成的表名
                .addInclude(TABLES)
                // 设置过滤表前缀
                //.addTablePrefix("t_")

                //controller配置
                .controllerBuilder()
                //覆盖已生成文件
                .enableFileOverride()
                //开启生成@RestController 控制器	默认值:false
                .enableRestStyle()

                //service配置
                .serviceBuilder()
                //覆盖已生成文件
                .enableFileOverride()
                .convertServiceFileName((entityName) -> entityName + "Service")
                .convertServiceImplFileName((entityName) -> entityName + "ServiceImpl")

                //mapper配置
                .mapperBuilder()
                //覆盖已生成文件
                .enableFileOverride()
                //启用 BaseResultMap 生成	默认值:false
                .enableBaseResultMap()
                //启用 BaseColumnList	默认值:false
                .enableBaseColumnList()
                //转换 mapper 类文件名称   默认值:%sMapper
                //.convertMapperFileName((entityName) -> entityName + "Mapper")
                //转换 xml 文件名称	默认值:%sMapper
                //.convertXmlFileName((entityName) -> entityName + "Mapper")

                //entity配置
                .entityBuilder()
                //覆盖已生成文件
                .enableFileOverride()
                //禁用生成 serialVersionUID	默认值:true
                .disableSerialVersionUID()
                //开启lombok模型	默认值:false
                .enableLombok()
                //开启Boolean类型字段移除is前缀	默认值:false mysql 数据库字段类型为tinyint(1)时，会自动转换为Boolean类型
                .enableRemoveIsPrefix()
                //乐观锁字段名(数据库字段)	versionColumnName与versionPropertyName二选一即可
                .versionColumnName("version")
                //逻辑删除字段名(数据库字段)	logicDeleteColumnName与logicDeletePropertyName二选一即可
                .logicDeleteColumnName("delete_flag")
                //转换文件名称
                //.convertFileName((entityName) -> entityName + "PO")
                //格式化文件名称
                //.formatFileName("%sPO")
                //全局主键类型
                .idType(IdType.ASSIGN_ID)
                .addTableFills(Arrays.asList(
                        new Column("create_time", FieldFill.INSERT),
                        new Column("created_by", FieldFill.INSERT),
                        new Column("update_time", FieldFill.INSERT_UPDATE),
                        new Column("updated_by", FieldFill.INSERT_UPDATE)
                ))

                .build();
    }

    @Before
    public void setUp() {
        initStrategyConfig();
    }

    @Test
    public void execute01() {
        AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
        generator.global(GLOBAL_CONFIG);
        generator.packageInfo(PACKAGE_CONFIG);
        generator.template(new TemplateConfig.Builder()
                .disable(TemplateType.CONTROLLER)
                .build());
        generator.strategy(strategyConfig);

        // 使用Freemarker引擎模板，默认的是Velocity引擎模板
        generator.execute(new FreemarkerTemplateEngine());
    }

    @Test
    public void execute02_SaveCommand() {
        AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
        generator.global(GLOBAL_CONFIG);
        generator.packageInfo(new PackageConfig.Builder()
                //设置父包名
                .parent(PKG_PARENT)
                //父包模块名	默认值:无
                .entity("model.command")
                .build());
        generator.template(new TemplateConfig.Builder()
                .disable()
                .entity("templates/entitySaveCommand.java")
                .build());

        strategyConfig.entity().getTableFillList().clear();
        generator.strategy(strategyConfig.entityBuilder()
                .convertFileName((entityName) -> entityName + "SaveCommand")
                .addIgnoreColumns("id", "version", "delete_flag", "create_time", "update_time", "updated_by")
                .build());

        generator.execute(new FreemarkerTemplateEngine());
    }

    @Test
    public void execute03_UpdateCommand() {
        DataSourceConfig DATA_SOURCE_CONFIG = new DataSourceConfig.Builder(DB_URL, DB_USERNAME, DB_PASSWORD)
                .typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
                    int typeCode = metaInfo.getJdbcType().TYPE_CODE;
                    if (typeCode == Types.SMALLINT) {
                        // 自定义类型转换
                        return DbColumnType.INTEGER;
                    }
                    if (typeCode == Types.BIGINT) {
                        // 自定义类型转换
                        return DbColumnType.STRING;
                    }
                    return typeRegistry.getColumnType(metaInfo);
                })
                .build();
        AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
        generator.global(GLOBAL_CONFIG);
        generator.packageInfo(new PackageConfig.Builder()
                //设置父包名
                .parent(PKG_PARENT)
                //父包模块名	默认值:无
                .entity("model.command")
                .build());
        generator.template(new TemplateConfig.Builder()
                .disable()
                .entity("templates/entityUpdateCommand.java")
                .build());

        strategyConfig.entity().getTableFillList().clear();
        generator.strategy(strategyConfig.entityBuilder()
                .convertFileName((entityName) -> entityName + "UpdateCommand")
                .addIgnoreColumns("delete_flag", "create_time", "created_by", "update_time")
                //清空标准设置中的version字段
                .versionColumnName("")
                .idType(null)
                .build());

        generator.execute(new FreemarkerTemplateEngine());
    }

    @Test
    public void execute04_DetailResp() {
        DataSourceConfig DATA_SOURCE_CONFIG = new DataSourceConfig.Builder(DB_URL, DB_USERNAME, DB_PASSWORD)
                .typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
                    int typeCode = metaInfo.getJdbcType().TYPE_CODE;
                    if (typeCode == Types.SMALLINT) {
                        // 自定义类型转换
                        return DbColumnType.INTEGER;
                    }
                    if (typeCode == Types.BIGINT) {
                        // 自定义类型转换
                        return DbColumnType.STRING;
                    }
                    return typeRegistry.getColumnType(metaInfo);
                })
                .build();
        AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
        generator.global(GLOBAL_CONFIG);
        generator.packageInfo(new PackageConfig.Builder()
                //设置父包名
                .parent(PKG_PARENT)
                //父包模块名	默认值:无
                .entity("model.resp")
                .build());
        generator.template(new TemplateConfig.Builder()
                .disable()
                .entity("templates/entityDetailResp.java")
                .build());

        strategyConfig.entity().getTableFillList().clear();
        generator.strategy(strategyConfig.entityBuilder()
                .convertFileName((entityName) -> entityName + "DetailResp")
                .addIgnoreColumns("delete_flag")
                //清空标准设置中的version字段
                .versionColumnName("")
                .idType(null)
                .build());

        generator.execute(new FreemarkerTemplateEngine());
    }

    @Test
    public void execute05_PageResp() {
        DataSourceConfig DATA_SOURCE_CONFIG = new DataSourceConfig.Builder(DB_URL, DB_USERNAME, DB_PASSWORD)
                .typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
                    int typeCode = metaInfo.getJdbcType().TYPE_CODE;
                    if (typeCode == Types.SMALLINT) {
                        // 自定义类型转换
                        return DbColumnType.INTEGER;
                    }
                    if (typeCode == Types.BIGINT) {
                        // 自定义类型转换
                        return DbColumnType.STRING;
                    }
                    return typeRegistry.getColumnType(metaInfo);
                })
                .build();
        AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
        generator.global(GLOBAL_CONFIG);
        generator.packageInfo(new PackageConfig.Builder()
                //设置父包名
                .parent(PKG_PARENT)
                //父包模块名	默认值:无
                .entity("model.resp")
                .build());
        generator.template(new TemplateConfig.Builder()
                .disable()
                .entity("templates/entityPageResp.java")
                .build());

        strategyConfig.entity().getTableFillList().clear();
        generator.strategy(strategyConfig.entityBuilder()
                .convertFileName((entityName) -> entityName + "PageResp")
                .addIgnoreColumns("delete_flag")
                //清空标准设置中的version字段
                .versionColumnName("")
                .idType(null)
                .build());

        generator.execute(new FreemarkerTemplateEngine());
    }

    @Test
    public void execute06_converter() {
        AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
        generator.global(GLOBAL_CONFIG);
        generator.packageInfo(new PackageConfig.Builder()
                //设置父包名
                .parent(PKG_PARENT)
                .entity(PKG_ENTITY)
                //父包模块名	默认值:无
                .controller("model.converter")
                .build());
        generator.template(new TemplateConfig.Builder()
                .disable()
                .controller("templates/converter.java")
                .build());

        generator.strategy(strategyConfig.controllerBuilder()
                .convertFileName((entityName) -> entityName + "Converter")
                .build());

        generator.execute(new FreemarkerTemplateEngine());
    }

    @Test
    public void execute07_controller() {
        AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
        generator.global(GLOBAL_CONFIG);
        generator.packageInfo(new PackageConfig.Builder()
                //设置父包名
                .parent(PKG_PARENT)
                .entity(PKG_ENTITY)
                .build());
        generator.template(new TemplateConfig.Builder()
                .disable()
                .controller("templates/controller.java")
                .build());

        generator.strategy(strategyConfig.controllerBuilder()
                .build());

        generator.execute(new FreemarkerTemplateEngine());
    }
}
